import { Model } from './model.js'
import { vector3Offset, convertColorFormat } from '../core/common.js'
let ModelHelper = {
  defaultRadius: null,
  innerHeight: 0,
  cache: {
    // scalePlane: null,
    // heightPlane: null,
    xAxes: null,
    yAxes: null,
    zAxes: null,
    xyPlane: null,
    curveTrack: null
  },
  primitive: {
    scalePlane: {
      name: 'modelHelper-scalePlane',
      position: [
        { x: 0.75, y: 0, z: 1.0 },
        { x: 0.75, y: 0, z: 1.06 },
        { x: 0.77, y: 0, z: 1.06 },
        { x: 0.77, y: 0, z: 1.04 },
        { x: 0.83, y: 0, z: 1.1 },
        { x: 0.81, y: 0, z: 1.1 },
        { x: 0.81, y: 0, z: 1.12 },
        { x: 0.87, y: 0, z: 1.12 },
        { x: 0.87, y: 0, z: 1.06 },
        { x: 0.85, y: 0, z: 1.06 },
        { x: 0.85, y: 0, z: 1.08 },
        { x: 0.79, y: 0, z: 1.02 },
        { x: 0.81, y: 0, z: 1.02 },
        { x: 0.81, y: 0, z: 1.0 }
      ],
      color: convertColorFormat('#00ff00'),
      alpha: 0.9
    },
    heightPlane: {
      name: 'modelHelper-heightPlane',
      position: [
        { x: 0.81, y: 0, z: 0.75 },
        { x: 0.75, y: 0, z: 0.81 },
        { x: 0.77, y: 0, z: 0.83 },
        { x: 0.79, y: 0, z: 0.81 },
        { x: 0.79, y: 0, z: 0.89 },
        { x: 0.77, y: 0, z: 0.87 },
        { x: 0.75, y: 0, z: 0.89 },
        { x: 0.81, y: 0, z: 0.95 },
        { x: 0.87, y: 0, z: 0.89 },
        { x: 0.85, y: 0, z: 0.87 },
        { x: 0.83, y: 0, z: 0.89 },
        { x: 0.83, y: 0, z: 0.81 },
        { x: 0.85, y: 0, z: 0.83 },
        { x: 0.87, y: 0, z: 0.81 }
      ],
      color: convertColorFormat('#0000ff'),
      alpha: 0.9
    },
    xAxes: {
      name: 'modelHelper-xAxes',
      position: [
        { y: 0.02, z: 0, x: 0.1 },
        { y: 0.02, z: 0, x: 1.02 },
        { y: 0.05, z: 0, x: 1 },
        { y: 0.07, z: 0, x: 1.02 },
        { y: 0, z: 0, x: 1.1 },
        { y: -0.07, z: 0, x: 1.02 },
        { y: -0.05, z: 0, x: 1 },
        { y: -0.02, z: 0, x: 1.02 },
        { y: -0.02, z: 0, x: 0.1 }
      ],
      color: convertColorFormat('#0000FF'),
      alpha: 0.9
    },
    yAxes: {
      name: 'modelHelper-yAxes',
      position: [
        { x: 0.02, z: 0, y: -0.1 },
        { x: 0.02, z: 0, y: -1.02 },
        { x: 0.05, z: 0, y: -1 },
        { x: 0.07, z: 0, y: -1.02 },
        { x: 0, z: 0, y: -1.1 },
        { x: -0.07, z: 0, y: -1.02 },
        { x: -0.05, z: 0, y: -1 },
        { x: -0.02, z: 0, y: -1.02 },
        { x: -0.02, z: 0, y: -0.1 }
      ],
      color: convertColorFormat('#00FF00'),
      alpha: 0.9
    },
    zAxes: {
      name: 'modelHelper-zAxes',
      position: [
        { x: 0.02, y: 0, z: 0.1 },
        { x: 0.02, y: 0, z: 1.02 },
        { x: 0.05, y: 0, z: 1 },
        { x: 0.07, y: 0, z: 1.02 },
        { x: 0, y: 0, z: 1.09 },
        { x: -0.07, y: 0, z: 1.02 },
        { x: -0.05, y: 0, z: 1 },
        { x: -0.02, y: 0, z: 1.02 },
        { x: -0.02, y: 0, z: 0.1 }
      ],
      color: convertColorFormat('#FF0000'),
      alpha: 0.9
    },
    xyPlane: {
      name: 'modelHelper-xyPlane',
      position: [...getArcData(0.09, 0.01, -0.01, null, 0, 360)],
      color: convertColorFormat('#ffffff'),
      alpha: 0.1
    },
    curveTrack: {
      name: 'modelHelper-curveTrack',
      position: [...getArcData(0.55, 0.01, -0.01, null, 5, 85), ...getArcData(0.5, 0.01, -0.01, true, 5, 85)],
      color: convertColorFormat('#00EBEB'),
      alpha: 0.5
    },
    selectedColor: convertColorFormat('#ffff00'),
    selectedAlpha: 0.9
  },
  _modelId: null,
  allowPick: false,
  showHelper: false,
  setHeight(height) {
    //调用函数，客户端无法直接属性赋值？
    this.innerHeight = height
  },
  //点击展示辅助坐标轴
  showAxesHeleper(modelId, cb) {
    this._modelId = modelId
    let model = Model._getModel({ id: this._modelId })
    let boundingVolume = Model._getBoundingVolume({
      id: this._modelId
    })
    if (!boundingVolume) return
    let boundingSphere = boundingVolume.boundingSphere
    let center = boundingSphere.center
    let radius = boundingSphere.radius
    let rotation = model.rotation.toEulerAngles()
    this._center = center
    this._radius = radius
    this.defaultRadius = radius
    //辅助轴中心点前移，不在模型包围球中心位置
    let origin = this.localToWorld(center, {
      offsetY: 0,
    })
    this.showHelper = true
    this.initAxesHelper(origin, null, radius) //初始化辅助坐标轴
    let backInfo = this.getBackInfo(this._modelId)
    cb && cb(backInfo)
  },
  mousedownEvent(e, cb) {
    if (this._disabled) {
      return
    }
    let cache = this.cache
    this._startPos = {
      x: e.x,
      y: e.y
    }
    let scene = GlobalViewer.scene
    let ray = scene.mainCamera.screenPointToRay(e.x, e.y) //相机过鼠标点射线
    let hit = new Li.RaycastHit()
    if (scene.raycast(ray, hit)) {
      //拾取场景内物体
      let entity = hit.entity
      if (entity) {
        let modelEntity = this.getModelEntity(entity)
        if (modelEntity) {
          //拾取物体为模型
          this.showAxesHeleper(modelEntity.tag, backInfo => {
            cb(backInfo); //选中模型
          })


          /* // 拾取到子节点
          if (entity.tag) {
            this._modelId = entity.tag
          } else {
            this._modelId = Model.addNode(entity)
          }
          let model = Model._getModel({ id: this._modelId })
          let boundingVolume = Model._getBoundingVolume({
            id: this._modelId
          })
          let boundingSphere = boundingVolume.boundingSphere
          let center = boundingSphere.center
          let radius = boundingSphere.radius
          let rotation = model.rotation.toEulerAngles()
          this._center = center
          this._radius = radius
          this.defaultRadius = radius
          //辅助轴中心点前移，不在模型包围球中心位置
          let origin = this.localToWorld(center, {
            offsetY: 0,
          })
          this.showHelper = true
          this.initAxesHelper(origin, null, radius) //初始化辅助坐标轴
          let backInfo = this.getBackInfo(this._modelId)
          backInfo.pick = true
          cb(backInfo)//选中glb节点 */
        } else {
          let objectName = entity.parent.objectName
          if (objectName && objectName.includes('modelHelper')) {
            //拾取物体为辅助坐标轴
            let name = objectName.split('-')[1]
            let model = Model._getModel({ id: this._modelId })
            let boundingVolume = Model._getBoundingVolume({
              id: this._modelId
            })
            let boundingSphere = boundingVolume.boundingSphere
            let center = boundingSphere.center
            let radius = boundingSphere.radius
            let rotation = model.rotation.toEulerAngles()
            this._helperName = name
            this._center = center
            this._radius = radius
            if (model.entity) {
              this._offset = {
                x: model.offset.x,
                y: model.offset.y,
                z: model.offset.z
              }
            } else {
              const { x, y, z } = model.transform.position
              this._offset = {
                x: x,
                y: -z,
                z: y
              }
            }//复制模型位置偏移,兼容客户端实时更新bug
            this._rotation = rotation
            this._scale = {
              x: model.scale.x,
              y: model.scale.y,
              z: model.scale.z
            }
            let mainCamera = scene.mainCamera
            let cameraController = mainCamera.cameraController()
            cameraController.enableInputs = false
            this._cameraController = cameraController
            //生成对应轴逻辑平面
            if (name == 'zAxes') {
              this._axesPlane = this.getAxesPlane(center, 'y')
            } else {
              this._axesPlane = this.getAxesPlane(center, 'z')
            }
            //获取鼠标起始位置在平面内点
            this._startRaycast = this.intersectPlane(ray)
            //标记辅助轴对应状态颜色
            for (const key in cache) {
              if (key == name) {
                let color = this.primitive.selectedColor
                let alpha = this.primitive.selectedAlpha
                cache[key].setFillColor(SSmap.Color.fromRgb(color.r, color.g, color.b, color.a))
                cache[key].alpha = alpha
                this.primitive[key].selected = true
              } else {
                let color = this.primitive[key].color
                cache[key].setFillColor(SSmap.Color.fromRgb(color.r, color.g, color.b, color.a))
                this.primitive[key].selected = false
              }
            }
            cb('true') //选中辅助轴
          }
        }
      }
    }
    hit.delete()
  },
  mousemoveEvent(e, cb) {
    if (this._helperName) {
      let origin = null
      //获取鼠标初始位置属性
      let offset = {
        x: this._offset.x,
        y: this._offset.y,
        z: this._offset.z
      }
      let rotation = {
        x: this._rotation.x,
        y: this._rotation.y,
        z: this._rotation.z
      }
      let camera = GlobalViewer.scene.mainCamera
      let cameraController = camera.cameraController()
      let ray = camera.screenPointToRay(e.x, e.y)
      //获取鼠标移动位置在平面内点
      let moveRaycast = this.intersectPlane(ray)
      if (this._startRaycast && moveRaycast) {
        //转为局部空间坐标
        let offsetTarget = this.worldToLocal(this._startRaycast, moveRaycast)
        let hypot,
          moveLength,
          deg = 0
        //设置对应轴属性
        let boundingVolume = Model._getBoundingVolume({
          id: this._modelId
        })
        let boundingSphere = boundingVolume.boundingSphere
        let center = boundingSphere.center
        let radius = boundingSphere.radius
        switch (this._helperName) {
          case 'scalePlane':
            if (e.movementY < 0) {
              // 鼠标往外移动，放大
              this._scale.x *= 1.01
              this._scale.y *= 1.01
              this._scale.z *= 1.01
              cameraController.zoomOut(2)
            } else if (e.movementY > 0) {
              // 鼠标往内移动，缩小
              this._scale.x /= 1.01
              this._scale.y /= 1.01
              this._scale.z /= 1.01
              cameraController.zoomIn(2)
            }

            this._center = center
            this._radius = radius
            break
          case 'heightPlane':
            if (e.movementY < 0) {
              // 鼠标往外移动，拉伸
              this._scale.z *= 1.01
              cameraController.zoomOut(2)
            } else if (e.movementY > 0) {
              // 鼠标往内移动，压缩
              this._scale.z /= 1.01
              cameraController.zoomIn(2)
            }
            this._center = center
            this._radius = radius
            break
          case 'xAxes':
            offset.x += offsetTarget.x
            break
          case 'yAxes':
            offset.y += offsetTarget.y
            break
          case 'zAxes':
            offset.z += offsetTarget.z
            break
          case 'xyPlane':
            offset.x += offsetTarget.x
            offset.y += offsetTarget.y
            break
          case 'curveTrack':
            //模型半径斜边距离旋转360度
            hypot = Math.sqrt(this._radius * this._radius + this._radius * this._radius)
            moveLength = Math.sqrt(offsetTarget.x * offsetTarget.x + offsetTarget.y * offsetTarget.y)
            deg = (moveLength / hypot) * 180
            if (offsetTarget.x >= 0 && offsetTarget.y >= 0) {
              rotation.z += deg
            } else if (offsetTarget.x <= 0 && offsetTarget.y <= 0) {
              rotation.z -= deg
            }
            break
          default:
            break
        }
        origin = this.localToWorld(this._center, {
          offsetX: offset.x - this._offset.x,
          offsetY: offset.y - this._offset.y,
          offsetZ: offset.z - this._offset.z
        })
        //更新辅助轴位置
        this.initAxesHelper(origin, null, this._radius)
        //更新模型属性
        Model.transform({
          id: this._modelId,
          offset: offset,
          rotation: rotation,
          scale: this._scale
        })
        let backInfo = this.getBackInfo(this._modelId)
        cb(backInfo)
      }
    }
  },
  mouseupEvent(cb) {
    if (this._offset) {
      let cache = this.cache
      for (const key in cache) {
        let color = this.primitive[key].color
        let alpha = this.primitive[key].alpha
        cache[key].setFillColor(SSmap.Color.fromRgb(color.r, color.g, color.b, color.a))
        cache[key].fillAlpha = alpha
        this.primitive[key].selected = false
      }
      this._cameraController.enableInputs = true
      this._offset = null
      this._rotation = null
      this._scale = null
      this._helperName = null
      this._axesPlane = null
      let backInfo = this.getBackInfo(this._modelId)
      cb(backInfo)
    }
  },
  getModelEntity(entity) {
    let model = null
    do {
      if (entity.objectName == 'Model') {
        model = entity
        break
      }
      entity = entity.parent
    } while (entity)
    return model
  },
  initAxesHelper(origin, rotation, scale) {
    if (this.showHelper) {
      // this.render('scalePlane', origin, rotation, scale)
      // this.render('heightPlane', origin, rotation, scale)
      this.render('xAxes', origin, rotation, scale)
      this.render('yAxes', origin, rotation, scale)
      this.render('zAxes', origin, rotation, scale)
      this.render('xyPlane', origin, rotation, scale)
      this.render('curveTrack', origin, rotation, scale)
    }
  },
  render(key, origin, rotation, scale, needChageDis) {
    let newScale = null
    if (!needChageDis) {
      newScale = {
        x: scale,
        y: scale,
        z: scale
      }
    } else {
      newScale = {
        x: needChageDis.includes('x') ? scale : this.defaultRadius,
        y: needChageDis.includes('y') ? scale : this.defaultRadius,
        z: needChageDis.includes('z') ? scale : this.defaultRadius
      }
    }
    let data = this.primitive[key]
    let position = data.position
    let points = []
    for (let i = 0; i < position.length; i += 1) {
      let point = this.localToWorld(
        origin,
        {
          offsetX: position[i].x,
          offsetY: position[i].y,
          offsetZ: position[i].z
        },
        rotation,
        newScale,
      )
      points.push(point)
    }
    if (this.cache[key]) {
      this.cache[key].delete()
      this.cache[key] = null
    }
    let color = data.selected ? this.primitive.selectedColor : data.color
    let alpha = data.selected ? this.primitive.selectedAlpha : data.alpha
    this.cache[key] = this.drayPolygon(points, data.name, color, alpha)
  },
  getAxesPlane(origin, direction) {
    let map = {
      x: 0,
      y: 1,
      z: 2
    }
    let scene = GlobalViewer.scene
    let globe = scene.globe
    let matrix = globe.ellipsoid.eastNorthUpToFixedFrame(origin.toCartesian3())
    let axes = matrix.column(map[direction])
    let normal = SSmap.Vector3.create(axes.x, axes.y, axes.z)
    let distance = SSmap.Vector3.dot(origin, normal)
    let plane = SSmap.Plane.create(normal, distance)
    return plane
  },
  distanceToPlane(ray, plane) {
    let denominator = SSmap.Vector3.dot(plane.normal, ray.direction)
    if (denominator == 0) {
      return null
    }
    let t = (SSmap.Vector3.dot(ray.origin, plane.normal) - plane.distance) / denominator
    return Math.abs(t)
  },
  intersectPlane(ray) {
    let plane = this._axesPlane
    let t = this.distanceToPlane(ray, plane)
    if (t == null) {
      return null
    }
    let target = SSmap.Vector3.multiplyByScalar(ray.direction, t)
    target = SSmap.Vector3.add(target, ray.origin)
    return target
  },
  localToWorld(worldPos, { offsetX = 0, offsetY = 0, offsetZ = 0 }, rotation, scale) {
    let scene = GlobalViewer.scene
    let globe = scene.globe
    let point = SSmap.Vector3.create(offsetX, offsetY, offsetZ)
    let matrix = globe.ellipsoid.eastNorthUpToFixedFrame(worldPos.toCartesian3())
    if (rotation) {
      rotation = SSmap.Quaternion.fromEulerAngles(rotation.x || 0, rotation.y || 0, rotation.z || 0)
      rotation = rotation.toRotationMatrix()
      let localMatrix = SSmap.Matrix4.fromRotationTranslation(rotation, SSmap.Vector3.create(0, 0, 0))
      matrix = SSmap.Matrix4.multiply(matrix, localMatrix)
    }
    if (scale) {
      let localMatrix = SSmap.Matrix4.fromScale(SSmap.Vector3.create(scale.x, scale.y, scale.z))
      matrix = SSmap.Matrix4.multiply(matrix, localMatrix)
    }
    let newPoint = SSmap.Matrix4.multiplyByVector3(matrix, point)
    return newPoint
  },
  worldToLocal(origin, target) {
    let scene = GlobalViewer.scene
    let globe = scene.globe
    let matrix = globe.ellipsoid.eastNorthUpToFixedFrame(origin.toCartesian3())
    let matrixInverse = matrix.inverted()
    target = SSmap.Matrix4.multiplyByVector3(matrixInverse, target)
    return target
  },
  drayPolygon(points, name, color, alpha) {
    let polygon = new SSmap.Polygon3D()
    // polygon.depthTestDistance = 0
    polygon.objectName = name
    polygon.color = SSmap.Color.fromRgb(color.r, color.g, color.b, color.a)
    polygon.alpha = 0.01
    polygon.fillAlpha = alpha
    polygon.setFillColor(SSmap.Color.fromRgb(color.r, color.g, color.b, color.a))
    polygon.setAltitudeMethod(SSmap.AltitudeMethod.Absolute)
    points.forEach((point) => {
      polygon.addPoint(point)
    })
    polygon.addProperty('name', 'polygon')
    polygon.draw()
    polygon.end()
    return polygon
  },
  updatePosition(newPosition) {
    const { id, position, rotation } = newPosition;
    //更新模型属性
    Model.transform({
      id: id,
      position: position,
      offset: {},  //偏移量初始化
      rotation: rotation,
    }, (modelId) => {
      let model = Model._getModel({ id: modelId })
      let boundingVolume = Model._getBoundingVolume({
        id: modelId
      })
      let boundingSphere = boundingVolume.boundingSphere
      let center = boundingSphere.center
      let radius = boundingSphere.radius
      let rotation = model.rotation.toEulerAngles()
      //辅助轴中心点前移，不在模型包围球中心位置
      let origin = this.localToWorld(center, {
        offsetY: 0,
      })
      //更新辅助轴位置
      if (this.showHelper) this.initAxesHelper(origin, null, radius)
    })
  },
  remove() {
    this.showHelper = false
    for (const key in this.cache) {
      if (this.cache[key]) {
        this.cache[key].delete()
        this.cache[key] = null
      }
    }
  },
  disable() {
    this._disabled = true
  },
  handlePcik(value) {
    this.allowPick = value
  },
  getBackInfo(modelId) {
    let model = Model._getModel({ id: modelId })
    let position = model.transform.worldMatrix.translation()
    let rotation = model.rotation.toEulerAngles()
    let objectName = null
    if (model.entity) {
      position = vector3Offset(position, {
        offsetX: model.offset.x,
        offsetY: model.offset.y,
        offsetZ: model.offset.z
      })
    } else {
      objectName = model.objectName
    }
    position = position.toCartographic().toDegrees()
    let backInfo = {
      id: modelId,
      // objectName: objectName,
      position: {
        longitude: position.longitude,
        latitude: position.latitude,
        height: position.height,
      },
      rotation: {
        x: rotation.x,
        y: rotation.y,
        z: rotation.z,
      }
      // scaleX: model.scale.x,
      // scaleZ: model.scale.z
    }
    return backInfo
  },
}
function getArcData(radius, x, y, reverse, minAngle, maxAngle) {
  let data = []
  for (let i = minAngle; i <= maxAngle; i++) {
    let radian = (Math.PI / 180) * i
    let point = {}
    point.x = radius * Math.cos(radian) + x
    point.y = -radius * Math.sin(radian) + y
    point.z = 0
    data.push(point)
  }
  if (reverse) {
    data.reverse()
  }
  return data
}
export { ModelHelper }
